use core::time;
use std::{borrow::BorrowMut, cell::RefCell, ops::Deref, rc::Rc, sync::{Arc, Mutex, mpsc}, thread::{self, sleep}, time::Duration};

use crossbeam::channel;

pub fn run(){
    test_crossbean_channel();
}
// crossbeam channel 和 select!的使用
fn test_crossbean_channel(){
    let (tx, rx) = crossbeam::channel::bounded::<i32>(10);
    //不同于标准库的 mpsc 这里的 tx rx 都实现了 send sync 可以在多线程间传递和使用
    let (tx2, rx2) = (tx.clone(), rx.clone());
    crossbeam::scope(|s|{
        s.spawn(|_|tx2.send(1));
        s.spawn(|_|tx2.send(2));
        s.spawn(|_|tx2.send(3));

        s.spawn(|_|{
            println!("i={}", rx2.recv().unwrap());
            println!("i={}", rx2.recv().unwrap());
            println!("i={}", rx2.recv().unwrap());
        });
    }).unwrap();
    println!("------------");
    // select!的使用 阻塞等待多个channel的接收

    let (t1, r1) = channel::unbounded::<i32>();
    let (t2, r2) = channel::unbounded::<i32>();

    let (t1, t2) = (t1.clone(), t2.clone());
    thread::spawn(move || {
        t1.send(1).unwrap();
        t2.send(2).unwrap();

        thread::sleep(Duration::from_secs(1));
        t1.send(3).unwrap();
    });
    // 每2秒发送一次数据
    let r3 = channel::tick(Duration::from_secs(2));
    // 5秒后发送一次数据，可以用作停止信号
    let r4 = channel::after(Duration::from_secs(5));
    loop {
        //同时监听 多个 channel，的事件，有消息就立刻返回
        crossbeam::select! {
            recv(r1) -> msg => println!("r1 recv {}", msg.unwrap_or_else(|e|{
                print!("r1 recv error:{}", e);
                -1
            })),
            recv(r2) -> msg => println!("r1 recv {}", msg.unwrap_or_else(|e|{
                print!("r2 recv error:{}", e);
                -1
            })),
            recv(r3) -> msg => println!("r3 recv {:?}", msg.unwrap()),
            recv(r4) -> _ => break,
            // 默认处理，如果两个channel都没有数据，1s之后则执行default
            default(Duration::from_secs(1)) => { println!("default"); }
        }
    }

    println!("main end!");
}
/// scope方法结束时 会阻塞等待 scope范围内的所有线程都结束
/// 实现了结构化并发的功能
fn test_crossbean_scope(){
    let arr:Vec<i32> = (0..1000).collect();

    let (left, right) = arr.split_at(500);
    let sum = crossbeam::scope(|scope|{
        let res1 = scope.spawn(|_|left.iter().sum::<i32>()).join().unwrap();
        let res2 = scope.spawn(|_|right.iter().sum::<i32>()).join().unwrap();
        res1+ res2
    }).unwrap();
    println!("sum={}", sum);
}
fn test_park(){
    let t1 = thread::spawn(||{
        println!("thread1 park");
        thread::park();
        println!("thread1 end");
    });

    thread::sleep(Duration::from_secs(2));
    //唤醒线程
    t1.thread().unpark();
    t1.join().unwrap();
    println!("main thread end");
}
fn test_thread_scope(){
    let count = vec![1,2,3];
    // 在 scope()闭包中 使用 scope发起的线程，如果没有被join在方法结束的时候都会被自动join
    // 也就是说在方法结束时所有的使用 scope发起的线程线程也会结束 
    let num = thread::scope(|scope|{
        println!("{:?}",count);

        scope.spawn( ||{
            println!("{:?}",&count);
        });
        scope.spawn(||{
            thread::sleep(Duration::from_secs(1));
            println!("{:?}",count);
        });
        18
    });
    println!("main count:{:?}", count);
}
fn share_in_thread() {
    let counter = Arc::new(Mutex::new(0));
    let c1 = Arc::clone(&counter);
    thread::spawn(move || {
        let mut num = c1.lock().unwrap();
        *num += 1;
    });
    let c2 = Arc::clone(&counter);
    let handler = thread::spawn(move || {
        let mut num = c2.lock().unwrap();
        *num += 2;
    });
    handler.join().unwrap();
    println!("counter={}", counter.deref().try_lock().unwrap());
}

fn message_mod() {
    let (tx, rx) = mpsc::channel();
    let tx2 = tx.clone();
    thread::spawn(move ||{
        let strs = vec!["jack".to_string(),"smith".to_string()];
        for str in strs {
            tx2.send(str).unwrap();
            sleep(Duration::from_secs(1));
        }
    });
    thread::spawn(move ||{
        let strs = vec!["jack".to_string(),"smith".to_string()];
        for str in strs {
            tx.send(str).unwrap();
            sleep(Duration::from_secs(1));
        }
    });
    for rec in rx {
        println!("rec={}", rec);
    }
}
fn parelle_print(){
    let handler = std::thread::spawn(runnable);

    for i in 1..30 {
        println!("main thread =======  i={}",i);
        std::thread::sleep(time::Duration::from_millis(10));
    }
    let _res = handler.join();
    println!("main thread end");
}
fn runnable(){
    for i in 1..30 {
        println!("child thread ------------- i={}",i);
        std::thread::sleep(time::Duration::from_millis(10));
    }
}